import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;

public class Table {

	public ArrayList<Agent> agents;
	private ArrayList<Card> cards;
	public ArrayList<Card> visibleCards = new ArrayList<Card>();
	public Hashtable<Agent, Integer> bets = new Hashtable<Agent, Integer>();
	public final int NUM_CARDS = 5;
	private int roundBet = 0;

	public Table(ArrayList<Agent> agts, ArrayList<Card> c)
	{
		agents = agts;
		cards = c;
		for (Agent a : agts)
		{
			bets.put(a, 0);
		}
	}

	public void endRound(Simulator s)
	{
		if (visibleCards.size() < NUM_CARDS)
		{
			nextCard();
		}
		else
		{
			endGame(s);
		}
	}

	private void nextCard()
	{
		do {
			Card next = cards.remove(0);
			visibleCards.add(next);
		} while (visibleCards.size() < 3);
	}

	private String traceCards()
	{
		String output = "";
		for (Card card : visibleCards)
		{
			output += card.toStringShort() + " ";
		}

		return output + "\n";
	}

	private String traceMoney()
	{
		String output = "Money: \n";
		for (Agent agent : agents)
		{
			if (!agent.getFold())
				output += agent.toString() +": "+agent.money + "\n";
			else
				output += agent.toString() +"(fold): "+agent.money + "\n";
		}

		return output;
	}

	public String toString()
	{
		String output = "Cards: ";
		output+= traceCards();
		output+= "Bet: "+getMaxBet()+"\n";
		output+= "Pot: "+getPot()+"\n";
		output+= traceMoney();

		return output;
	}

	public int getMaxBet()
	{
		int maxBet = 0;
		for (Agent agt : bets.keySet())
		{
			int bet =  bets.get(agt);
			if (bet > maxBet)
				maxBet = bet;
		}
		return maxBet;
	}
	
	public void resetRoundBet()
	{
		roundBet = 0;
	}
	
	public void addRoundBet(int b)
	{
		roundBet = b;
	}
	
	public int getRoundBet()
	{
		return roundBet;
	}

	public int getPot()
	{
		int pot = 0;
		for (Agent agt : bets.keySet())
		{
			pot += bets.get(agt);
		}
		return pot;
	}

	/**
	 * Gives the player all the cards that it can't see, which is the
	 * deck + cards the other agents hold
	 * @return
	 */
	public ArrayList<Card> getCards(Agent agent)
	{
		ArrayList<Card> cloneDeck = new ArrayList<Card>();
		for (Card c:cards)
		{
			cloneDeck.add(c.clone());
		}
		for (Agent a:agents)
		{
			if (a == agent)
				continue;

			for (Card c:a.cards)
				cloneDeck.add(c.clone());
		}
		Collections.shuffle(cloneDeck);

		return cloneDeck;
	}

	public ArrayList<Card> getVisibleCards()
	{
		ArrayList<Card> cloneDeck = new ArrayList<Card>();
		for (Card c:visibleCards)
		{
			cloneDeck.add(c.clone());
		}
		return cloneDeck;
	}

	public void endGame(Simulator s){ s.endGame();}

	public Agent getWinner()
	{
		//Did someone win by everyone else folding?
		int numAgents = agents.size();
		for (Agent agt : agents)
		{
			if (agt.getFold())
				numAgents --;
		}
		if (numAgents == 1)
		{
			for (Agent agt: agents)
				if (!agt.getFold())
					return agt;
		}

		//Otherwise, best hand wins
		Collections.sort(agents);
		Collections.reverse(agents);
		return agents.get(0);
	}

}
